home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Technical Documentation / PCI Information / PCI Developer’s Kit (disk) / Open Firmware / SCSI example / scsidisk.of < prev    next >
Encoding:
Text File  |  1994-06-27  |  4.5 KB  |  152 lines  |  [TEXT/EDIT]

  1. \ SCSI disk package implementing a "block" device-type interface.
  2.  
  3. " sd" xdrstring  " name" attribute
  4. " block"     device-type
  5.  
  6. fload scsicom.fth        \ Utility routines for SCSI commands
  7.  
  8. hex
  9.  
  10. \ 0 means no timeout
  11. : set-timeout  ( msecs -- )  " set-timeout" $call-parent  ;
  12.  
  13. 0 instance value offset-low     \ Offset to start of partition
  14. 0 instance value offset-high
  15.  
  16. 0 instance value label-package
  17.  
  18. \ Sets offset-low and offset-high, reflecting the starting location of the
  19. \ partition specified by the "my-args" string.
  20.  
  21. : init-label-package  ( -- okay? )
  22.    0 is offset-high  0 is offset-low
  23.    my-args  " disk-label"  $open-package is label-package
  24.    label-package  if
  25.       0 0  " offset" label-package $call-method  is offset-high is offset-low
  26.       true
  27.    else
  28.       ." Can't open disk label package"  cr  false
  29.    then
  30. ;
  31.  
  32.  
  33. \ Ensures that the disk is spinning, but doesn't wait forever
  34.  
  35. create sstart-cmd  h# 1b c, 1 c, 0 c, 0 c, 1 c, 0 c,
  36.  
  37. : timed-spin  ( -- error? )
  38.    d# 15000 set-timeout
  39.    sstart-cmd  no-data-command
  40.    0 set-timeout
  41. ;
  42.  
  43. 0 instance value /block         \ Device native block size
  44.  
  45. create mode-sense-cmd     h# 1a c, 0 c, 0 c, 0 c, d# 12 c, 0 c,
  46. create read-capacity-cmd  h# 25 c, 0 c, 0 c, 0 c, d# 12 c, 0 c,
  47.                               0 c, 0 c, 0 c, 0 c, 
  48.  
  49. : read-block-size  ( -- n )     \ Ask device about its block size
  50.    \ First try "mode sense" - data returned in bytes 9,10,11
  51.  
  52.    d# 12  mode-sense-cmd 6  short-data-command  if  0  else  9 + 3c@  then
  53.  
  54.    ?dup  if  exit  then
  55.  
  56.    \ Failing that, try "read capacity" - data returned in bytes 4,5,6,7
  57.  
  58.    8  read-capacity-cmd 0a  short-data-command   if  0  else  4 + 4c@  then
  59.  
  60.    ?dup  if  exit  then
  61.  
  62.    d# 512               \ Default to 512 if the device won't tell us
  63. ;
  64.  
  65. external
  66.  
  67. \ Return device block size; cache it the first time we find the information
  68. \ This method is called by the deblocker
  69. : block-size  ( -- n )
  70.    /block  if  /block exit  then        \ Don't ask if we already know
  71.  
  72.    read-block-size dup is /block
  73. ;
  74.  
  75. headers
  76.  
  77. \ Read or write "#blks" blocks starting at "block#" into memory at "addr"
  78. \ Input? is true for reading or false for writing.
  79. \ command is  8  for reading or  h# a  for writing
  80. \ We use the 6-byte forms of the disk read and write commands.
  81.  
  82. : 2c!  ( n addr -- )  >r lbsplit 2drop  r> +c!         c!  ;
  83. : 4c!  ( n addr -- )  >r lbsplit        r> +c! +c! +c! c!  ;
  84.  
  85. : r/w-blocks  ( addr block# #blks input? command -- actual# )
  86.    3 pick  h# 100000 u>=  if  \ Use 10-byte form  ( addr block# #blks dir cmd )
  87.       h# 20 or  0 cb!  \ 28 (read) or 2a (write)  ( addr block# #blks dir )
  88.       -rot swap                                   ( addr dir #blks block# )
  89.       cmdbuf 2 + 4c!                              ( addr dir #blks )
  90.       dup cmdbuf 7 + 2c!
  91.    else                        \ Use 6-byte form  ( addr block# #blks dir cmd )
  92.       0 cb!                                       ( addr block# #blks dir )
  93.       -rot swap                                   ( addr dir #blks block# )
  94.       cmdbuf 1+ 3c!                               ( addr dir #blks )
  95.       dup 4 cb!                                   ( addr dir #blks )
  96.    then
  97.    dup >r                                         ( addr input? #blks )
  98.    /block *  swap  cmdbuf 6  -1      ( addr #bytes input? cmd cmdlen #retries )
  99.    retry-command  if                              ( [ sensebuf ] hw? )
  100.       0= if  drop  then  r> drop 0
  101.    else
  102.       r>
  103.    then    ( actual# )
  104. ;
  105.  
  106. external
  107.  
  108. \ These three methods are called by the deblocker.
  109.  
  110. : max-transfer  ( -- n )   parent-max-transfer  ;
  111. : read-blocks   ( addr block# #blocks -- #read )     true  d# 8  r/w-blocks  ;
  112. : write-blocks  ( addr block# #blocks -- #written )  false d# 10 r/w-blocks  ;
  113.  
  114. \ Methods used by external clients
  115.  
  116. : open  ( -- flag )
  117.    my-unit " set-address" $call-parent
  118.  
  119.    \ It might be a good idea to do an inquiry here to determine the
  120.    \ device configuration, checking the result to see if the device
  121.    \ really is a disk.
  122.  
  123.    \ Make sure the disk is spinning
  124.  
  125.    timed-spin  if  false exit  then
  126.  
  127.    block-size is /block
  128.  
  129.    init-deblocker  0=  if  false exit  then
  130.  
  131.    init-label-package  0=  if
  132.       deblocker close-package false exit
  133.    then
  134.  
  135.    true
  136. ;
  137.  
  138. : close  ( -- )
  139.    label-package close-package
  140.    deblocker close-package
  141. ;
  142.  
  143. : seek  ( offset.low offset.high -- okay? )
  144.    offset-low offset-high  x+  " seek"   deblocker $call-method
  145. ;
  146.  
  147. : read  ( addr len -- actual-len )  " read"  deblocker $call-method  ;
  148. : write ( addr len -- actual-len )  " write" deblocker $call-method  ;
  149. : load  ( addr -- size )            " load"  label-package $call-method  ;
  150.  
  151. headers
  152.